package com.tool.payment.util;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize.Inclusion;

public class JsonUtils {

	private static final Logger LOG = Logger.getLogger(JsonUtils.class);
	 
	private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
	
	private static ObjectMapper MAPPER;
	
	static{
		MAPPER = generateMapper(Inclusion.ALWAYS);
	}
	
	private JsonUtils(){}
	
	public static <T> T jsonToObj(String json, TypeReference<T> typeReference) {
    	if(StringUtils.isNotEmpty(json)){
    		try {
                return MAPPER.readValue(json, typeReference);
            } catch (JsonParseException e) {
                LOG.error("JsonParseException: ", e);
            } catch (JsonMappingException e) {
                LOG.error("JsonMappingException: ", e);
            } catch (IOException e) {
                LOG.error("IOException: ", e);
            }
    	}
        return null;
    }
	
	 public static <T> List<T> jsonToList(String json, Class<T> valueType) {
    	if(StringUtils.isNotEmpty(json)){
    		try {
    			List<T> resultList = new ArrayList<T>();
    			List<Map<?, ?>> list = MAPPER.readValue(json, List.class);
    			for(Map<?, ?> obj : list){
    				resultList.add(MAPPER.convertValue(obj, valueType));
    			}
                return resultList;
            } catch (JsonParseException e) {
                LOG.error("JsonParseException: ", e);
            } catch (JsonMappingException e) {
                LOG.error("JsonMappingException: ", e);
            } catch (IOException e) {
                LOG.error("IOException: ", e);
            }
    	}
        return null;
    }
	 
	 public static Map<?,?> objToMap(Object obj) {
    	Map<String, Object> map = MAPPER.convertValue(obj, Map.class);
    	Map<String, Object> result = new HashMap<String, Object>();
    	for(Entry<String, Object> item : map.entrySet()){
    		if(null != item.getValue()){
    			result.put(item.getKey(), item.getValue());
    		}
    	}
        return result;
    }
	 
	 public static <T> T toObj(Object obj, Class<T> typeReference) {
	    	T  result = MAPPER.convertValue(obj, typeReference);
	        return result;
	    }
	 
	 public static <T> T jsonToObj(String json, Class<T> valueType) {
	    	if(StringUtils.isNotEmpty(json)){
	    		try {
	                return MAPPER.readValue(json, valueType);
	            } catch (JsonParseException e) {
	                LOG.error("JsonParseException: ", e);
	            } catch (JsonMappingException e) {
	                LOG.error("JsonMappingException: ", e);
	            } catch (IOException e) {
	                LOG.error("IOException: ", e);
	            }
	    	}
	        return null;
	    }
	 
	 public static String objToJson(Object object) {
	    	if(object != null){
	    		try {
	                return MAPPER.writeValueAsString(object);
	            } catch (JsonGenerationException e) {
	                LOG.error("JsonGenerationException: ", e);
	            } catch (JsonMappingException e) {
	                LOG.error("JsonMappingException: ", e);
	            } catch (IOException e) {
	                LOG.error("IOException: ", e);
	            }
	    	}
	        return null;
	    }
	 
	 public static <T> T fromJson(String json, Class<T> clazz) {
	    	if(StringUtils.isNotEmpty(json)){
	    		try {
	                return clazz.equals(String.class) ? (T) json : MAPPER.readValue(json, clazz);
	            } catch (JsonParseException e) {
	                LOG.error("JsonParseException: ", e);
	            } catch (JsonMappingException e) {
	                LOG.error("JsonMappingException: ", e);
	            } catch (IOException e) {
	                LOG.error("IOException: ", e);
	            }
	    	}
	        return null;
	    }
	 
	 public static <T> T fromJson(String json, TypeReference<?> typeReference){
	    	if(StringUtils.isNotEmpty(json)){
	    		try {
	                return (T) (typeReference.getType().equals(String.class) ? json : MAPPER.readValue(json, typeReference));
	            } catch (JsonParseException e) {
	                LOG.error("JsonParseException: ", e);
	            } catch (JsonMappingException e) {
	                LOG.error("JsonMappingException: ", e);
	            } catch (IOException e) {
	                LOG.error("IOException: ", e);
	            }
	    	}
	        return null;
	    }
	 
	 public static <T> String toJson(T src)  {
	        try {
	            return src instanceof String ? (String) src : MAPPER.writeValueAsString(src);
	        } catch (JsonProcessingException e) {
	            LOG.error("JsonParseException: ", e);
	        }
	        return null;
	    }
	 
	private static ObjectMapper generateMapper(Inclusion inclusion) {

        ObjectMapper customMapper = new ObjectMapper();
        // 所有日期格式都统一为以下样式
        customMapper.setDateFormat(new SimpleDateFormat(DATE_TIME_FORMAT));

        return customMapper;
    }
}
